package com.hevs.samplewebapp.client.services;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.JsArray;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.Window;
import com.hevs.samplewebapp.client.Patient;
import com.hevs.samplewebapp.client.bean.CompositeWRefresh;
import com.hevs.samplewebapp.client.bean.DoctorJson;
import com.hevs.samplewebapp.client.bean.FakeSyncRestCall;
import com.hevs.samplewebapp.client.bean.JSONHelper;
import com.hevs.samplewebapp.client.bean.MedicalDataItem;
import com.hevs.samplewebapp.client.bean.MedicalDataJson;
import com.hevs.samplewebapp.client.bean.User;
import com.hevs.samplewebapp.client.dialogbox.ServerResponseMessages;
import com.hevs.samplewebapp.client.services.MedicalDataService;

/**
 * Implementation of the Medical data service Interface
 * 
 * @author Thomas Rouvinez
 * @date 23.03.2012
 */
public class MedicalDataServiceImpl implements MedicalDataService{

	/**
	 * List of doctors granted by the patient
	 */
	private List<User> doctors = new ArrayList<User>();

	/**
	 * List of the medical data
	 */
	private List<MedicalDataItem> records = new ArrayList<MedicalDataItem>();


	@Override
	/**
	 * Method to delete a medical data or revoke a doctor.
	 */
	public void sendDELETE(String url, JSONObject json) {
		RequestBuilder builder=new RequestBuilder(RequestBuilder.POST,url);

		try
		{
			@SuppressWarnings("unused")
			Request response = builder.sendRequest(json.toString(), new RequestCallback()
			{
				public void onError(Request request,Throwable exception)
				{
					Window.alert("Error while sending JSON to Server");
				}

				public void onResponseReceived(Request request,Response response)
				{
					if(response.getStatusCode() == 200)
						Window.alert("Successfully deleted!");
					else
						ServerResponseMessages.statusCode(response.getStatusCode());
				}
			});
		}
		catch(RequestException e)
		{
			e.printStackTrace();
			Window.alert("Failed to send the Request");
		}
	}


	@Override
	/**
	 * Method to send a new medical data.
	 */
	public void sendPOST(String url, JSONArray jsonArray) {
		{
			RequestBuilder builder=new RequestBuilder(RequestBuilder.POST,url);

			try
			{
				@SuppressWarnings("unused")
				Request response=builder.sendRequest(jsonArray.toString(),
						new RequestCallback()
				{
					public void onError(Request request,Throwable exception)
					{
						Window.alert("Error while sending JSON to Server");
					}

					public void onResponseReceived(Request request,Response response)
					{    
						if(response.getStatusCode() == 200)
							Window.alert("Successfully added new data!");
						else
							ServerResponseMessages.statusCode(response.getStatusCode());
					}
				});
			}
			catch(RequestException e)
			{
				e.printStackTrace();
				Window.alert("Failed to send the Request");
			}
		}
	}


	@Override
	/**
	 * Method to refresh a list of medical data.
	 */
	public void sendGetAllMedicalRecords(CompositeWRefresh comp){
		String url = Patient.JSON_URL_MEDICALDATA;
		url = URL.encode(url);
		RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);

		try{
			@SuppressWarnings("unused")
			Request request = builder.sendRequest(null, new FakeSyncRestCall(comp) {


				public void onError(Request request, Throwable exception) {
					Window.alert("Error while sending JSON to Server");
				}

				public void onResponseReceived(Request request, Response response) {
					if(200 == response.getStatusCode()){
						setRecords(JSONHelper.asArrayOfMedicalData(response.getText()));
						refresh();
					}else
						ServerResponseMessages.statusCode(response.getStatusCode());
				}
			});
		}
		catch(RequestException e){
			e.printStackTrace();
			Window.alert("Failed to send the Request");
		}
	}

	/**
	 * Method to transform a medical data from JSON to Java object
	 * @param recordsJson
	 * List of medical data in JSON format
	 */
	public void setRecords(JsArray<MedicalDataJson> recordsJson){

		records.clear();

		for (int i = 0; i < recordsJson.length(); i++) {
			MedicalDataItem record = new MedicalDataItem();
			record.setId(recordsJson.get(i).getKey());
			record.setValue(recordsJson.get(i).getValue());
			record.setCategory(recordsJson.get(i).getCategory());
			record.setType(recordsJson.get(i).getType());
			record.setDate(recordsJson.get(i).getDate());
			records.add(record);
		}
	}

	/**
	 * Getter for the Medical data List
	 * @return
	 * a List of medical data
	 */
	public List<MedicalDataItem> getRecords(){
		return records;
	}

	@Override
	/**
	 * Method to update a medical data or granting a doctor.
	 */
	public void sendPUT(String url,JSONObject json)
	{
		RequestBuilder builder=new RequestBuilder(RequestBuilder.PUT,url);
		try
		{
			@SuppressWarnings("unused")
			Request response=builder.sendRequest(json.toString(),new RequestCallback()
			{
				public void onError(Request request,Throwable exception)
				{
					Window.alert("Error while sending JSON to Server");
				}

				public void onResponseReceived(Request request,Response response)
				{
					if(response.getStatusCode() == 200)
						Window.alert("Successfully updated!");
					else
						ServerResponseMessages.statusCode(response.getStatusCode());
				}
			});
		}
		catch(RequestException e)
		{
			e.printStackTrace();
			Window.alert("Failed to send the Request");
		}
	}

	/**
	 * Method to retriev the List of granted doctor
	 */
	public void sendGetAllDoctor(CompositeWRefresh comp){
		String url = Patient.JSON_URL_GRANT;
		url = URL.encode(url);
		RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
		try{
			@SuppressWarnings("unused")
			Request request = builder.sendRequest(null, new FakeSyncRestCall(comp) {

				public void onError(Request request, Throwable exception) {
					Window.alert("Error while sending JSON to Server");
				}

				public void onResponseReceived(Request request, Response response) {
					if(200 == response.getStatusCode()){
						setDoctors(JSONHelper.asArrayOfDoctor(response.getText()));
						refresh();
					}
				}
			});
		}
		catch(RequestException e){
			e.printStackTrace();
			Window.alert("Failed to send the Request");
		}
	}

	/**
	 * Method to grant a doctor
	 * @param doctorsJson
	 * Json format of a Doctor
	 */
	public void setDoctors(JsArray<DoctorJson> doctorsJson){
		doctors = new ArrayList<User>();

		for (int i = 0; i < doctorsJson.length(); i++) {
			User doctor = new User();
			doctor.setFirstName(doctorsJson.get(i).getFirstName());
			doctor.setLastName(doctorsJson.get(i).getLastName());
			doctor.setEmail(doctorsJson.get(i).getEmail());
			doctors.add(doctor);
		}
	}

	/**
	 * Getter for the list of granted doctors
	 * @return
	 * List of Doctor in Java object format
	 */
	public List<User> getDoctors()
	{
		return this.doctors;
	}

	@Override
	/**
	 * Method to grant access to a doctor
	 * @param url
	 * URL of the web service
	 * @param json
	 * email of the doctor in JSON format
	 */
	public void sendPOSTGrantDoctor(String url,JSONObject json)
	{
		RequestBuilder builder=new RequestBuilder(RequestBuilder.POST,url);
		try
		{
			@SuppressWarnings("unused")
			Request response=builder.sendRequest(json.toString(),new RequestCallback()
			{
				public void onError(Request request,Throwable exception)
				{
					Window.alert("Error while sending JSON to Server");
				}

				public void onResponseReceived(Request request,Response response)
				{
					if(response.getStatusCode() == 200)
						Window.alert("Successfully granted!");
					else
						ServerResponseMessages.statusCode(response.getStatusCode());                               
				}
			});
		}
		catch(RequestException e)
		{
			e.printStackTrace();
			Window.alert("Failed to send the Request");
		}
	}
}
